﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EventBus
{
  public  class InMemoryEventStore: IEventStore
    {

        private readonly ConcurrentDictionary<Type, List<IEventHandlerFactory>> _eventAndHandlerMapping;

        public InMemoryEventStore()
        {

            _eventAndHandlerMapping = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
        }




        private List<IEventHandlerFactory> GetOrCreateHandlerFactories(Type eventType)
        {
            return _eventAndHandlerMapping.GetOrAdd(eventType, (type) => new List<IEventHandlerFactory>());
        }

    

        public void Add(Type eventType, IEventHandlerFactory factory)
        {
            GetOrCreateHandlerFactories(eventType).Add(factory);
        }


        public void Remove<TEventData>(Action<TEventData> action) where TEventData : IEventData
        {
            GetOrCreateHandlerFactories(typeof(TEventData)).RemoveAll(factory =>
            {
                var handler = factory as ActionEventHandler<TEventData>;
                return handler.Action == action;

            });
        }

   
        public void Remove(Type eventType, IEventHandler eventHandler)
        {
            GetOrCreateHandlerFactories(eventType).RemoveAll(factory => factory?.GetHandlerType() == eventHandler.GetType());

        }

        public void RemoveAll(Type eventType)
        {
            GetOrCreateHandlerFactories(eventType).Clear();
        }

       public  IDictionary<Type, IEventHandlerFactory[]> GetHandlers(Type eventType)
        {
            return _eventAndHandlerMapping.Where(item => item.Key == eventType || item.Key.IsAssignableFrom(eventType))
                .ToDictionary(item => item.Key, item => item.Value.ToArray());
        }

      
    }
}
